{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 1. Glossary\n",
    "In order to make the best use of this User Guide, it is important to have context for some high level concepts and terms. Here is a small glossary of some of the most important concepts in Bokeh.\n",
    "\n",
    "为了充分利用本用户指南，有一些高级概念和术语的上下文非常重要。 以下是 Bokeh 一些最重要概念的术语表。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1.1 Application\n",
    "A Bokeh application is a recipe for generating Bokeh documents. Typically this is Python code run by a Bokeh server when new sessions are created.\n",
    "\n",
    "Bokeh 应用程序是生成 Bokeh 文档的诀窍。 通常这是在创建新会话时由 Bokeh 服务器运行的 Python 代码。\n",
    "\n",
    "## 1.2 BokehJS\n",
    "The JavaScript client library that actually renders the visuals and handles the UI interactions for Bokeh plots and widgets in the browser. Typically, users will not have to think about this aspect of Bokeh much (“We write the JavaScript, so you don’t have to!”) but it is good to have basic knowledge of this dichotomy. For full details, see the `BokehJS` chapter of the Developers.\n",
    "\n",
    "这个JavaScript客户端库实际上呈现视觉效果，并处理浏览器中Bokeh plots和小部件的UI交互。 通常情况下，用户不必过多考虑Bokeh的这一方面(“我们编写JavaScript，所以您不必这样做! ”) 但是对这种知识有基本的了解是很好的。 有关详细信息，请参阅`BokehJS`的开发者章节。\n",
    "\n",
    "## 1.3 Documents\n",
    "An organizing data structure for Bokeh applications. Documents contain all the Bokeh Models and data needed to render an interactive visualization or application in the browser.\n",
    "\n",
    "一种用于Bokeh应用程序的组织数据结构。 文档包含在浏览器中呈现交互式可视化或应用程序所需的所有Bokeh模型和数据。\n",
    "\n",
    "## 1.4 Embedding\n",
    "Various methods of including Bokeh plots and widgets into web apps and pages, or the IPython notebook. See `Embedding Bokeh Content` for more details.\n",
    "\n",
    "各种方法，包括散景图和小工具到网络应用程序和网页，或IPython笔记本电脑。有关更多细节，请参见`Embedding Bokeh Content`。\n",
    "\n",
    "## 1.5 Glyphs\n",
    "The basic visual building blocks of Bokeh plots, e.g. lines, rectangles, squares, wedges, patches, etc. The `bokeh.plotting` interface provides a convenient way to create plots centered around glyphs. See `Plotting with Basic Glyphs` for more information.\n",
    "\n",
    "基本视觉效果由一些模块构成，例如直线、长方形、正方形、楔形、斑块等。 `bokeh.plotting`界面提供了一种方便的方法来创建以glyphs为中心的绘图。 有关更多信息，请参见`Plotting with Basic Glyphs`。\n",
    "\n",
    "## 1.6 Models\n",
    "The lowest-level objects that comprise Bokeh “scenegraphs”. These live in the bokeh.models interface. Most users will not use this level of interface to assemble plots directly. However, ultimately all Bokeh plots consist of collections of models, so it is important to understand them enough to configure their attributes and properties. See Styling Visual Attributes for more information.\n",
    "\n",
    "组成散景图的最底层对象。 它们存在于 bokeh.models 界面中。 大多数用户不会使用这个级别的界面来直接组装图表。 然而，最终所有 Bokeh 绘图都是由模型集合组成的，因此充分理解它们以配置它们的属性和属性非常重要。 有关更多信息，请参见样式化可视化属性。\n",
    "\n",
    "## 1.7 Server\n",
    "The Bokeh server is an optional component that can be used for sharing and publishing Bokeh plots and apps, for handling streaming of large data sets, or for enabling sophisticated user interactions based off of widgets and selections. See `Running a Bokeh Server` for more explanation.\n",
    "\n",
    "服务器是一个可选组件，可用于分享和发布Bokeh plots和应用程序，用于处理大型数据集的流，或用于启用基于小部件和选择的复杂用户交互。 更多解释请参见`Running a Bokeh Server`。\n",
    "\n",
    "## 1.8 Widgets\n",
    "User interface elements outside of a Bokeh plot such as sliders, drop down menus, buttons, etc. Events and updates from widgets can inform additional computations, or cause Bokeh plots to update. Widgets can be used in both standalone applications or with the Bokeh server. For examples and information, see Making Interactions.\n",
    "\n",
    "Bokeh plot之外的用户界面元素，如滑块、下拉菜单、按钮等。 来自小部件的事件和更新可以通知额外的计算，或者导致Bokeh plots更新。 小部件可以在独立应用程序中使用，也可以在Bokeh服务器中使用。有关示例和信息，请参见进行互动。\n",
    "\n",
    "---"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 2. Output Methods\n",
    "As we will see demonstrated frequently throughout the User Guide, there are various ways to generate output for Bokeh documents. The most common for interactive usage are:\n",
    "\n",
    "正如我们将在用户指南中经常看到的那样，有多种方法可以为Bokeh文档生成输出。 最常见的交互式应用是:\n",
    "\n",
    "1. output_file\n",
    "\n",
    "For generating simple standalone HTML documents for Bokeh visualizations.\n",
    "用于为Bokeh可视化生成简单的独立HTML文档。\n",
    "\n",
    "2. output_notebook\n",
    "\n",
    "For displaying Bokeh visualizations inline in Jupyter/Zeppelin notebook cells.\n",
    "用于在jupyter/zeppelin笔记本电脑中显示Bokeh可视化效果。\n",
    "\n",
    "\n",
    "These functions are most often used together with the show or save functions.\n",
    "这些函数通常与显示或保存函数一起使用。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 3. Interface\n",
    "Bokeh is intended to provide a quick and simple interface to data scientists and domain experts who do not want to be distracted by the details of the software, and also provide a richly detailed interface to application developers and software engineers who may want more control or access to more sophisticated features. Because of this, Bokeh takes a layered approach and offers different programming interfaces appropriate to different levels of use. This section provides an overview of the various interfaces that are available to Bokeh users, as well as more context about the most important concepts central to the library. If you’d like to jump right into basic plotting, go to `Plotting with Basic Glyphs`.\n",
    "\n",
    "目的是为那些不想被软件细节分心的数据科学家和领域专家提供一个快速而简单的界面，同时也为那些想要更多控制或访问更复杂功能的应用程序开发人员和软件工程师提供一个丰富而详细的界面。 因此，Bokeh 采用了分层的方法，并提供了适合不同级别使用的不同编程接口。 本节概述 Bokeh 用户可以使用的各种接口，以及关于库中最重要的概念的更多上下文。 如果你想直接进入基本绘图，可以进入`Plotting with Basic Glyphs`。\n",
    "\n",
    "## 3.1 bokeh.models\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Bokeh is actually composed of two library components.\n",
    "\n",
    "Bokeh 实际上是由两个库组件组成的。\n",
    "\n",
    "The first component is a JavaScript library, BokehJS, that runs in the browser. This library is responsible for all of the rendering and user interaction. Its input is a collection of declarative JSON objects that comprise a “scenegraph”. The objects in this scenegraph describe everything that BokehJS should handle: what plots and widgets are present and in what arrangement, what tools and renderers and axes the plots will have, etc. These JSON objects are converted into BokehJS Models in the browser, and are rendered by corresponding BokehJS Views.\n",
    "\n",
    "第一个组件是在浏览器中运行的JavaScript库BokehJS。这个库负责所有的渲染和用户交互。它的输入是组成“scenegraph”的具有声明性的JSON对象集合。 这个场景图中的对象描述了BokehJS应该处理的所有事情: 图表和小部件是什么样的，以什么样的方式排列，图表将有什么样的工具、渲染器和轴线，等等。 这些JSON对象在浏览器中被转换成BokehJS模型，并由相应的BokehJS视图呈现。\n",
    "\n",
    "The second component is a library in Python (or other languages) that can generate the JSON described above. In the Python Bokeh library, this is accomplished at the lowest level by exposing a set of “model” classes that exactly mirror the set of BokehJS Models that are created in the browser. These python model classes know how to validate their content and attributes, and also how to serialize themselves to JSON. All of these low level models live in the low-level bokeh.models interface. Most of the models are very simple, usually consisting of a few property attributes and no methods. Model attributes can either be configured when the model is created, or later by setting attribute values on the model object. Here are some examples for a Rect glyph object:\n",
    "\n",
    "第二个组件是Python(或其他语言)中的一个库，它可以生成上面描述的JSON。在Python Bokeh库中，这是通过公开一组“模型”类来实现的，这些类完全反映了在浏览器中创建的BokehJS模型集。 这些python模型类知道如何验证它们的内容和属性，以及如何将自己序列化到JSON。所有这些低级模型都存在于低级 bokeh.models接口中。大多数模型都非常简单，通常只包含一些属性属性，没有方法。可以在创建模型时配置模型属性，或者稍后通过在模型对象上设置属性值来配置模型属性。下面是一些Rect标志符号对象的例子:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# properties can be configured when a model object is initialized\n",
    "glyph = Rect(x=\"x\", y=\"y2\", w=10, h=20, line_color=None)\n",
    "\n",
    "# or by assigning values to attributes on the model later\n",
    "glyph.fill_alpha = 0.5\n",
    "glyph.fill_color = \"navy\""
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "These methods of configuration work in general for all Bokeh models. Because of that, and because all Bokeh interfaces ultimately produce collections of Bokeh models, styling and configuring plots and widgets is accomplished in basically the same way, regardless of which interface is used.\n",
    "\n",
    "这些配置方法通常适用于所有Bokeh模型。正因为如此，并且因为所有Bokeh界面最终都会产生Bokeh模型的集合，所以无论使用哪个界面，设计和配置plots和widgets的方式基本上都是相同的。\n",
    "\n",
    "Using the bokeh.models interface provides complete control over how Bokeh plots and Bokeh widgets are put together and configured. However, it provides no help with assembling the models in meaningful or correct ways. It is entirely up to developers to build the scenegraph “by hand”. For this reason, most users will probably want to use the `bokeh.plotting` interface described below, unless they have specialized requirements that necessitate finer control. For more information about the details of all Bokeh models, consult the Reference.\n",
    "\n",
    "使用Bokeh.models界面可以完全控制如何将Bokeh绘图和Bokeh小部件放在一起并进行配置。但是，它并没有提供以有意义的或正确的方式组装模型的帮助。 这完全取决于开发人员“手工”构建风景图。 出于这个原因，大多数用户可能希望使用下面描述的`bokeh.plotting`接口，除非他们有需要更精细控制的特殊需求。有关所有Bokeh模型的详细信息，请参阅参考资料。"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 3.2 bokeh.plotting\n",
    "\n",
    "Bokeh provides a mid-level general purpose `bokeh.plotting` interface, which is similar in specificity to Matplotlib or Matlab style plotting interfaces. It is centered around having users relate the visual glyphs they would like to have displayed to their data, and otherwise taking care of putting together plots with sensible default axes, grids, and tools. All the hard work to assemble the appropriate Bokeh Models to form a scenegraph that BokehJS can render is handled automatically.\n",
    "\n",
    "Bokeh提供了一个中级通用的`Bokeh.plotting`接口，它与Matplotlib或Matlab风格的绘图接口类似。它的核心是让用户将他们希望显示的视觉图形与他们的数据联系起来，否则就要用合理的默认轴、网格和工具把图形放在一起。组装适当的Bokeh模型以形成一个BokehJS可以渲染的场景图的所有艰苦工作都是自动处理的。\n",
    "\n",
    "The main class in the `bokeh.plotting` interface is the figure() function. This creates a Figure model, that includes methods for adding different kinds of glyphs to a plot. Additionally it composes default axes, grids, and tools in the proper way without any extra effort.\n",
    "\n",
    "`Bokeh.plotting`接口中的主类是figure()函数。这将创建一个图形模型，其中包括将不同类型的图形添加到绘图中的方法。此外，它以正确的方式组合默认轴、网格和工具，而不需要任何额外的工作。\n",
    "\n",
    "A prototypical example of the `bokeh.plotting` usage is show below, along with the resulting plot:\n",
    "\n",
    "下面显示了` bokeh.plotting` 使用的一个典型例子，以及由此产生的情节:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "\n",
       "    <div class=\"bk-root\">\n",
       "        <a href=\"https://bokeh.pydata.org\" target=\"_blank\" class=\"bk-logo bk-logo-small bk-logo-notebook\"></a>\n",
       "        <span id=\"1120\">Loading BokehJS ...</span>\n",
       "    </div>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/javascript": [
       "\n",
       "(function(root) {\n",
       "  function now() {\n",
       "    return new Date();\n",
       "  }\n",
       "\n",
       "  var force = true;\n",
       "\n",
       "  if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n",
       "    root._bokeh_onload_callbacks = [];\n",
       "    root._bokeh_is_loading = undefined;\n",
       "  }\n",
       "\n",
       "  var JS_MIME_TYPE = 'application/javascript';\n",
       "  var HTML_MIME_TYPE = 'text/html';\n",
       "  var EXEC_MIME_TYPE = 'application/vnd.bokehjs_exec.v0+json';\n",
       "  var CLASS_NAME = 'output_bokeh rendered_html';\n",
       "\n",
       "  /**\n",
       "   * Render data to the DOM node\n",
       "   */\n",
       "  function render(props, node) {\n",
       "    var script = document.createElement(\"script\");\n",
       "    node.appendChild(script);\n",
       "  }\n",
       "\n",
       "  /**\n",
       "   * Handle when an output is cleared or removed\n",
       "   */\n",
       "  function handleClearOutput(event, handle) {\n",
       "    var cell = handle.cell;\n",
       "\n",
       "    var id = cell.output_area._bokeh_element_id;\n",
       "    var server_id = cell.output_area._bokeh_server_id;\n",
       "    // Clean up Bokeh references\n",
       "    if (id != null && id in Bokeh.index) {\n",
       "      Bokeh.index[id].model.document.clear();\n",
       "      delete Bokeh.index[id];\n",
       "    }\n",
       "\n",
       "    if (server_id !== undefined) {\n",
       "      // Clean up Bokeh references\n",
       "      var cmd = \"from bokeh.io.state import curstate; print(curstate().uuid_to_server['\" + server_id + \"'].get_sessions()[0].document.roots[0]._id)\";\n",
       "      cell.notebook.kernel.execute(cmd, {\n",
       "        iopub: {\n",
       "          output: function(msg) {\n",
       "            var id = msg.content.text.trim();\n",
       "            if (id in Bokeh.index) {\n",
       "              Bokeh.index[id].model.document.clear();\n",
       "              delete Bokeh.index[id];\n",
       "            }\n",
       "          }\n",
       "        }\n",
       "      });\n",
       "      // Destroy server and session\n",
       "      var cmd = \"import bokeh.io.notebook as ion; ion.destroy_server('\" + server_id + \"')\";\n",
       "      cell.notebook.kernel.execute(cmd);\n",
       "    }\n",
       "  }\n",
       "\n",
       "  /**\n",
       "   * Handle when a new output is added\n",
       "   */\n",
       "  function handleAddOutput(event, handle) {\n",
       "    var output_area = handle.output_area;\n",
       "    var output = handle.output;\n",
       "\n",
       "    // limit handleAddOutput to display_data with EXEC_MIME_TYPE content only\n",
       "    if ((output.output_type != \"display_data\") || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n",
       "      return\n",
       "    }\n",
       "\n",
       "    var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n",
       "\n",
       "    if (output.metadata[EXEC_MIME_TYPE][\"id\"] !== undefined) {\n",
       "      toinsert[toinsert.length - 1].firstChild.textContent = output.data[JS_MIME_TYPE];\n",
       "      // store reference to embed id on output_area\n",
       "      output_area._bokeh_element_id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n",
       "    }\n",
       "    if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n",
       "      var bk_div = document.createElement(\"div\");\n",
       "      bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n",
       "      var script_attrs = bk_div.children[0].attributes;\n",
       "      for (var i = 0; i < script_attrs.length; i++) {\n",
       "        toinsert[toinsert.length - 1].firstChild.setAttribute(script_attrs[i].name, script_attrs[i].value);\n",
       "      }\n",
       "      // store reference to server id on output_area\n",
       "      output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n",
       "    }\n",
       "  }\n",
       "\n",
       "  function register_renderer(events, OutputArea) {\n",
       "\n",
       "    function append_mime(data, metadata, element) {\n",
       "      // create a DOM node to render to\n",
       "      var toinsert = this.create_output_subarea(\n",
       "        metadata,\n",
       "        CLASS_NAME,\n",
       "        EXEC_MIME_TYPE\n",
       "      );\n",
       "      this.keyboard_manager.register_events(toinsert);\n",
       "      // Render to node\n",
       "      var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n",
       "      render(props, toinsert[toinsert.length - 1]);\n",
       "      element.append(toinsert);\n",
       "      return toinsert\n",
       "    }\n",
       "\n",
       "    /* Handle when an output is cleared or removed */\n",
       "    events.on('clear_output.CodeCell', handleClearOutput);\n",
       "    events.on('delete.Cell', handleClearOutput);\n",
       "\n",
       "    /* Handle when a new output is added */\n",
       "    events.on('output_added.OutputArea', handleAddOutput);\n",
       "\n",
       "    /**\n",
       "     * Register the mime type and append_mime function with output_area\n",
       "     */\n",
       "    OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n",
       "      /* Is output safe? */\n",
       "      safe: true,\n",
       "      /* Index of renderer in `output_area.display_order` */\n",
       "      index: 0\n",
       "    });\n",
       "  }\n",
       "\n",
       "  // register the mime type if in Jupyter Notebook environment and previously unregistered\n",
       "  if (root.Jupyter !== undefined) {\n",
       "    var events = require('base/js/events');\n",
       "    var OutputArea = require('notebook/js/outputarea').OutputArea;\n",
       "\n",
       "    if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n",
       "      register_renderer(events, OutputArea);\n",
       "    }\n",
       "  }\n",
       "\n",
       "  \n",
       "  if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n",
       "    root._bokeh_timeout = Date.now() + 5000;\n",
       "    root._bokeh_failed_load = false;\n",
       "  }\n",
       "\n",
       "  var NB_LOAD_WARNING = {'data': {'text/html':\n",
       "     \"<div style='background-color: #fdd'>\\n\"+\n",
       "     \"<p>\\n\"+\n",
       "     \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n",
       "     \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n",
       "     \"</p>\\n\"+\n",
       "     \"<ul>\\n\"+\n",
       "     \"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\\n\"+\n",
       "     \"<li>use INLINE resources instead, as so:</li>\\n\"+\n",
       "     \"</ul>\\n\"+\n",
       "     \"<code>\\n\"+\n",
       "     \"from bokeh.resources import INLINE\\n\"+\n",
       "     \"output_notebook(resources=INLINE)\\n\"+\n",
       "     \"</code>\\n\"+\n",
       "     \"</div>\"}};\n",
       "\n",
       "  function display_loaded() {\n",
       "    var el = document.getElementById(\"1120\");\n",
       "    if (el != null) {\n",
       "      el.textContent = \"BokehJS is loading...\";\n",
       "    }\n",
       "    if (root.Bokeh !== undefined) {\n",
       "      if (el != null) {\n",
       "        el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n",
       "      }\n",
       "    } else if (Date.now() < root._bokeh_timeout) {\n",
       "      setTimeout(display_loaded, 100)\n",
       "    }\n",
       "  }\n",
       "\n",
       "\n",
       "  function run_callbacks() {\n",
       "    try {\n",
       "      root._bokeh_onload_callbacks.forEach(function(callback) {\n",
       "        if (callback != null)\n",
       "          callback();\n",
       "      });\n",
       "    } finally {\n",
       "      delete root._bokeh_onload_callbacks\n",
       "    }\n",
       "    console.debug(\"Bokeh: all callbacks have finished\");\n",
       "  }\n",
       "\n",
       "  function load_libs(css_urls, js_urls, callback) {\n",
       "    if (css_urls == null) css_urls = [];\n",
       "    if (js_urls == null) js_urls = [];\n",
       "\n",
       "    root._bokeh_onload_callbacks.push(callback);\n",
       "    if (root._bokeh_is_loading > 0) {\n",
       "      console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n",
       "      return null;\n",
       "    }\n",
       "    if (js_urls == null || js_urls.length === 0) {\n",
       "      run_callbacks();\n",
       "      return null;\n",
       "    }\n",
       "    console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n",
       "    root._bokeh_is_loading = css_urls.length + js_urls.length;\n",
       "\n",
       "    function on_load() {\n",
       "      root._bokeh_is_loading--;\n",
       "      if (root._bokeh_is_loading === 0) {\n",
       "        console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n",
       "        run_callbacks()\n",
       "      }\n",
       "    }\n",
       "\n",
       "    function on_error() {\n",
       "      console.error(\"failed to load \" + url);\n",
       "    }\n",
       "\n",
       "    for (var i = 0; i < css_urls.length; i++) {\n",
       "      var url = css_urls[i];\n",
       "      const element = document.createElement(\"link\");\n",
       "      element.onload = on_load;\n",
       "      element.onerror = on_error;\n",
       "      element.rel = \"stylesheet\";\n",
       "      element.type = \"text/css\";\n",
       "      element.href = url;\n",
       "      console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n",
       "      document.body.appendChild(element);\n",
       "    }\n",
       "\n",
       "    for (var i = 0; i < js_urls.length; i++) {\n",
       "      var url = js_urls[i];\n",
       "      var element = document.createElement('script');\n",
       "      element.onload = on_load;\n",
       "      element.onerror = on_error;\n",
       "      element.async = false;\n",
       "      element.src = url;\n",
       "      console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n",
       "      document.head.appendChild(element);\n",
       "    }\n",
       "  };var element = document.getElementById(\"1120\");\n",
       "  if (element == null) {\n",
       "    console.error(\"Bokeh: ERROR: autoload.js configured with elementid '1120' but no matching script tag was found. \")\n",
       "    return false;\n",
       "  }\n",
       "\n",
       "  function inject_raw_css(css) {\n",
       "    const element = document.createElement(\"style\");\n",
       "    element.appendChild(document.createTextNode(css));\n",
       "    document.body.appendChild(element);\n",
       "  }\n",
       "\n",
       "  var js_urls = [\"https://cdn.pydata.org/bokeh/release/bokeh-1.2.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-widgets-1.2.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-tables-1.2.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-gl-1.2.0.min.js\"];\n",
       "  var css_urls = [\"https://cdn.pydata.org/bokeh/release/bokeh-1.2.0.min.css\", \"https://cdn.pydata.org/bokeh/release/bokeh-widgets-1.2.0.min.css\", \"https://cdn.pydata.org/bokeh/release/bokeh-tables-1.2.0.min.css\"];\n",
       "\n",
       "  var inline_js = [\n",
       "    function(Bokeh) {\n",
       "      Bokeh.set_log_level(\"info\");\n",
       "    },\n",
       "    \n",
       "    function(Bokeh) {\n",
       "      \n",
       "    },\n",
       "    function(Bokeh) {} // ensure no trailing comma for IE\n",
       "  ];\n",
       "\n",
       "  function run_inline_js() {\n",
       "    \n",
       "    if ((root.Bokeh !== undefined) || (force === true)) {\n",
       "      for (var i = 0; i < inline_js.length; i++) {\n",
       "        inline_js[i].call(root, root.Bokeh);\n",
       "      }if (force === true) {\n",
       "        display_loaded();\n",
       "      }} else if (Date.now() < root._bokeh_timeout) {\n",
       "      setTimeout(run_inline_js, 100);\n",
       "    } else if (!root._bokeh_failed_load) {\n",
       "      console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n",
       "      root._bokeh_failed_load = true;\n",
       "    } else if (force !== true) {\n",
       "      var cell = $(document.getElementById(\"1120\")).parents('.cell').data().cell;\n",
       "      cell.output_area.append_execute_result(NB_LOAD_WARNING)\n",
       "    }\n",
       "\n",
       "  }\n",
       "\n",
       "  if (root._bokeh_is_loading === 0) {\n",
       "    console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n",
       "    run_inline_js();\n",
       "  } else {\n",
       "    load_libs(css_urls, js_urls, function() {\n",
       "      console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n",
       "      run_inline_js();\n",
       "    });\n",
       "  }\n",
       "}(window));"
      ],
      "application/vnd.bokehjs_load.v0+json": "\n(function(root) {\n  function now() {\n    return new Date();\n  }\n\n  var force = true;\n\n  if (typeof root._bokeh_onload_callbacks === \"undefined\" || force === true) {\n    root._bokeh_onload_callbacks = [];\n    root._bokeh_is_loading = undefined;\n  }\n\n  \n\n  \n  if (typeof (root._bokeh_timeout) === \"undefined\" || force === true) {\n    root._bokeh_timeout = Date.now() + 5000;\n    root._bokeh_failed_load = false;\n  }\n\n  var NB_LOAD_WARNING = {'data': {'text/html':\n     \"<div style='background-color: #fdd'>\\n\"+\n     \"<p>\\n\"+\n     \"BokehJS does not appear to have successfully loaded. If loading BokehJS from CDN, this \\n\"+\n     \"may be due to a slow or bad network connection. Possible fixes:\\n\"+\n     \"</p>\\n\"+\n     \"<ul>\\n\"+\n     \"<li>re-rerun `output_notebook()` to attempt to load from CDN again, or</li>\\n\"+\n     \"<li>use INLINE resources instead, as so:</li>\\n\"+\n     \"</ul>\\n\"+\n     \"<code>\\n\"+\n     \"from bokeh.resources import INLINE\\n\"+\n     \"output_notebook(resources=INLINE)\\n\"+\n     \"</code>\\n\"+\n     \"</div>\"}};\n\n  function display_loaded() {\n    var el = document.getElementById(\"1120\");\n    if (el != null) {\n      el.textContent = \"BokehJS is loading...\";\n    }\n    if (root.Bokeh !== undefined) {\n      if (el != null) {\n        el.textContent = \"BokehJS \" + root.Bokeh.version + \" successfully loaded.\";\n      }\n    } else if (Date.now() < root._bokeh_timeout) {\n      setTimeout(display_loaded, 100)\n    }\n  }\n\n\n  function run_callbacks() {\n    try {\n      root._bokeh_onload_callbacks.forEach(function(callback) {\n        if (callback != null)\n          callback();\n      });\n    } finally {\n      delete root._bokeh_onload_callbacks\n    }\n    console.debug(\"Bokeh: all callbacks have finished\");\n  }\n\n  function load_libs(css_urls, js_urls, callback) {\n    if (css_urls == null) css_urls = [];\n    if (js_urls == null) js_urls = [];\n\n    root._bokeh_onload_callbacks.push(callback);\n    if (root._bokeh_is_loading > 0) {\n      console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n      return null;\n    }\n    if (js_urls == null || js_urls.length === 0) {\n      run_callbacks();\n      return null;\n    }\n    console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n    root._bokeh_is_loading = css_urls.length + js_urls.length;\n\n    function on_load() {\n      root._bokeh_is_loading--;\n      if (root._bokeh_is_loading === 0) {\n        console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n        run_callbacks()\n      }\n    }\n\n    function on_error() {\n      console.error(\"failed to load \" + url);\n    }\n\n    for (var i = 0; i < css_urls.length; i++) {\n      var url = css_urls[i];\n      const element = document.createElement(\"link\");\n      element.onload = on_load;\n      element.onerror = on_error;\n      element.rel = \"stylesheet\";\n      element.type = \"text/css\";\n      element.href = url;\n      console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n      document.body.appendChild(element);\n    }\n\n    for (var i = 0; i < js_urls.length; i++) {\n      var url = js_urls[i];\n      var element = document.createElement('script');\n      element.onload = on_load;\n      element.onerror = on_error;\n      element.async = false;\n      element.src = url;\n      console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n      document.head.appendChild(element);\n    }\n  };var element = document.getElementById(\"1120\");\n  if (element == null) {\n    console.error(\"Bokeh: ERROR: autoload.js configured with elementid '1120' but no matching script tag was found. \")\n    return false;\n  }\n\n  function inject_raw_css(css) {\n    const element = document.createElement(\"style\");\n    element.appendChild(document.createTextNode(css));\n    document.body.appendChild(element);\n  }\n\n  var js_urls = [\"https://cdn.pydata.org/bokeh/release/bokeh-1.2.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-widgets-1.2.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-tables-1.2.0.min.js\", \"https://cdn.pydata.org/bokeh/release/bokeh-gl-1.2.0.min.js\"];\n  var css_urls = [\"https://cdn.pydata.org/bokeh/release/bokeh-1.2.0.min.css\", \"https://cdn.pydata.org/bokeh/release/bokeh-widgets-1.2.0.min.css\", \"https://cdn.pydata.org/bokeh/release/bokeh-tables-1.2.0.min.css\"];\n\n  var inline_js = [\n    function(Bokeh) {\n      Bokeh.set_log_level(\"info\");\n    },\n    \n    function(Bokeh) {\n      \n    },\n    function(Bokeh) {} // ensure no trailing comma for IE\n  ];\n\n  function run_inline_js() {\n    \n    if ((root.Bokeh !== undefined) || (force === true)) {\n      for (var i = 0; i < inline_js.length; i++) {\n        inline_js[i].call(root, root.Bokeh);\n      }if (force === true) {\n        display_loaded();\n      }} else if (Date.now() < root._bokeh_timeout) {\n      setTimeout(run_inline_js, 100);\n    } else if (!root._bokeh_failed_load) {\n      console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n      root._bokeh_failed_load = true;\n    } else if (force !== true) {\n      var cell = $(document.getElementById(\"1120\")).parents('.cell').data().cell;\n      cell.output_area.append_execute_result(NB_LOAD_WARNING)\n    }\n\n  }\n\n  if (root._bokeh_is_loading === 0) {\n    console.debug(\"Bokeh: BokehJS loaded, going straight to plotting\");\n    run_inline_js();\n  } else {\n    load_libs(css_urls, js_urls, function() {\n      console.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n      run_inline_js();\n    });\n  }\n}(window));"
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "text/html": [
       "\n",
       "\n",
       "\n",
       "\n",
       "\n",
       "\n",
       "  <div class=\"bk-root\" id=\"b40b6b1c-2892-4493-88ce-8ef0babd7d22\" data-root-id=\"1089\"></div>\n"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    },
    {
     "data": {
      "application/javascript": [
       "(function(root) {\n",
       "  function embed_document(root) {\n",
       "    \n",
       "  var docs_json = {\"70ea0301-06c4-48e1-93d7-2fc217c61bfa\":{\"roots\":{\"references\":[{\"attributes\":{\"below\":[{\"id\":\"1098\",\"type\":\"LinearAxis\"}],\"center\":[{\"id\":\"1102\",\"type\":\"Grid\"},{\"id\":\"1107\",\"type\":\"Grid\"}],\"left\":[{\"id\":\"1103\",\"type\":\"LinearAxis\"}],\"plot_height\":300,\"plot_width\":300,\"renderers\":[{\"id\":\"1118\",\"type\":\"GlyphRenderer\"}],\"title\":{\"id\":\"1129\",\"type\":\"Title\"},\"toolbar\":{\"id\":\"1111\",\"type\":\"Toolbar\"},\"x_range\":{\"id\":\"1090\",\"type\":\"DataRange1d\"},\"x_scale\":{\"id\":\"1094\",\"type\":\"LinearScale\"},\"y_range\":{\"id\":\"1092\",\"type\":\"DataRange1d\"},\"y_scale\":{\"id\":\"1096\",\"type\":\"LinearScale\"}},\"id\":\"1089\",\"subtype\":\"Figure\",\"type\":\"Plot\"},{\"attributes\":{\"text\":\"\"},\"id\":\"1129\",\"type\":\"Title\"},{\"attributes\":{\"source\":{\"id\":\"1115\",\"type\":\"ColumnDataSource\"}},\"id\":\"1119\",\"type\":\"CDSView\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.1},\"fill_color\":{\"value\":\"#1f77b4\"},\"line_alpha\":{\"value\":0.1},\"line_color\":{\"value\":\"#1f77b4\"},\"radius\":{\"units\":\"data\",\"value\":0.3},\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"1117\",\"type\":\"Circle\"},{\"attributes\":{},\"id\":\"1134\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{\"dimension\":1,\"ticker\":{\"id\":\"1104\",\"type\":\"BasicTicker\"}},\"id\":\"1107\",\"type\":\"Grid\"},{\"attributes\":{\"formatter\":{\"id\":\"1132\",\"type\":\"BasicTickFormatter\"},\"ticker\":{\"id\":\"1104\",\"type\":\"BasicTicker\"}},\"id\":\"1103\",\"type\":\"LinearAxis\"},{\"attributes\":{},\"id\":\"1136\",\"type\":\"UnionRenderers\"},{\"attributes\":{},\"id\":\"1094\",\"type\":\"LinearScale\"},{\"attributes\":{\"ticker\":{\"id\":\"1099\",\"type\":\"BasicTicker\"}},\"id\":\"1102\",\"type\":\"Grid\"},{\"attributes\":{\"fill_alpha\":{\"value\":0.5},\"fill_color\":{\"value\":\"#1f77b4\"},\"line_alpha\":{\"value\":0.5},\"line_color\":{\"value\":\"#1f77b4\"},\"radius\":{\"units\":\"data\",\"value\":0.3},\"x\":{\"field\":\"x\"},\"y\":{\"field\":\"y\"}},\"id\":\"1116\",\"type\":\"Circle\"},{\"attributes\":{},\"id\":\"1109\",\"type\":\"ResetTool\"},{\"attributes\":{\"formatter\":{\"id\":\"1134\",\"type\":\"BasicTickFormatter\"},\"ticker\":{\"id\":\"1099\",\"type\":\"BasicTicker\"}},\"id\":\"1098\",\"type\":\"LinearAxis\"},{\"attributes\":{},\"id\":\"1099\",\"type\":\"BasicTicker\"},{\"attributes\":{},\"id\":\"1110\",\"type\":\"SaveTool\"},{\"attributes\":{},\"id\":\"1096\",\"type\":\"LinearScale\"},{\"attributes\":{},\"id\":\"1108\",\"type\":\"PanTool\"},{\"attributes\":{\"data_source\":{\"id\":\"1115\",\"type\":\"ColumnDataSource\"},\"glyph\":{\"id\":\"1116\",\"type\":\"Circle\"},\"hover_glyph\":null,\"muted_glyph\":null,\"nonselection_glyph\":{\"id\":\"1117\",\"type\":\"Circle\"},\"selection_glyph\":null,\"view\":{\"id\":\"1119\",\"type\":\"CDSView\"}},\"id\":\"1118\",\"type\":\"GlyphRenderer\"},{\"attributes\":{\"callback\":null},\"id\":\"1090\",\"type\":\"DataRange1d\"},{\"attributes\":{\"callback\":null},\"id\":\"1092\",\"type\":\"DataRange1d\"},{\"attributes\":{\"active_drag\":\"auto\",\"active_inspect\":\"auto\",\"active_multi\":null,\"active_scroll\":\"auto\",\"active_tap\":\"auto\",\"tools\":[{\"id\":\"1108\",\"type\":\"PanTool\"},{\"id\":\"1109\",\"type\":\"ResetTool\"},{\"id\":\"1110\",\"type\":\"SaveTool\"}]},\"id\":\"1111\",\"type\":\"Toolbar\"},{\"attributes\":{},\"id\":\"1104\",\"type\":\"BasicTicker\"},{\"attributes\":{\"callback\":null,\"data\":{\"x\":[1,2.5,3,2],\"y\":[2,3,1,1.5]},\"selected\":{\"id\":\"1135\",\"type\":\"Selection\"},\"selection_policy\":{\"id\":\"1136\",\"type\":\"UnionRenderers\"}},\"id\":\"1115\",\"type\":\"ColumnDataSource\"},{\"attributes\":{},\"id\":\"1132\",\"type\":\"BasicTickFormatter\"},{\"attributes\":{},\"id\":\"1135\",\"type\":\"Selection\"}],\"root_ids\":[\"1089\"]},\"title\":\"Bokeh Application\",\"version\":\"1.2.0\"}};\n",
       "  var render_items = [{\"docid\":\"70ea0301-06c4-48e1-93d7-2fc217c61bfa\",\"roots\":{\"1089\":\"b40b6b1c-2892-4493-88ce-8ef0babd7d22\"}}];\n",
       "  root.Bokeh.embed.embed_items_notebook(docs_json, render_items);\n",
       "\n",
       "  }\n",
       "  if (root.Bokeh !== undefined) {\n",
       "    embed_document(root);\n",
       "  } else {\n",
       "    var attempts = 0;\n",
       "    var timer = setInterval(function(root) {\n",
       "      if (root.Bokeh !== undefined) {\n",
       "        embed_document(root);\n",
       "        clearInterval(timer);\n",
       "      }\n",
       "      attempts++;\n",
       "      if (attempts > 100) {\n",
       "        console.log(\"Bokeh: ERROR: Unable to run BokehJS code because BokehJS library is missing\");\n",
       "        clearInterval(timer);\n",
       "      }\n",
       "    }, 10, root)\n",
       "  }\n",
       "})(window);"
      ],
      "application/vnd.bokehjs_exec.v0+json": ""
     },
     "metadata": {
      "application/vnd.bokehjs_exec.v0+json": {
       "id": "1089"
      }
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "from bokeh.plotting import figure, output_notebook, show\n",
    "\n",
    "# create a Figure object\n",
    "p = figure(plot_width=300, plot_height=300, tools=\"pan,reset,save\")\n",
    "\n",
    "# add a Circle renderer to this figure\n",
    "p.circle([1, 2.5, 3, 2], [2, 3, 1, 1.5], radius=0.3, alpha=0.5)\n",
    "\n",
    "# specify how to output the plot(s)\n",
    "#output_file(\"foo.html\")\n",
    "output_notebook()\n",
    "\n",
    "# display the figure\n",
    "show(p)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The main observation is that the typical usage involves creating plots objects with the `figure()` function, then using the glyph methods like `Figure.circle` to add renderers for our data. We do not have to worry about configuring any axes or grids (although we can configure them if we need to), and specifying tools is done simply with the names of tools to add. Finally we use some output functions to display our plot.\n",
    "\n",
    "主要的观察结果是，典型的使用方法包括使用`figure()`函数创建plot对象，然后使用诸如`Figure.circle`之类的标志符号方法为我们的数据添加渲染器。 我们不必担心配置任何轴或网格(尽管我们可以根据需要配置它们) ，指定工具只需要添加工具的名称。 最后，我们使用一些输出函数来显示我们的图。\n",
    "\n",
    "There are many other possibilities: saving our plot instead of showing it, styling or removing the axes or grids, adding additional renderers, and laying out multiple plots together. The Plotting with Basic Glyphs section of this User Guide will walk through many more examples and common use cases of using the `bokeh.plotting` interface.\n",
    "\n",
    "还有许多其他的可能性: 保存我们的情节而不是显示它，造型或删除轴或网格，添加额外的渲染器，并布置多个情节在一起。 本用户指南的基本字形绘制部分将介绍更多使用`bokeh.Plotting`接口的示例和常见用例。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
